package web.suzy.oj.manager.msg;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.shiro.SecurityUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import web.suzy.oj.common.exception.StatusFailException;
import web.suzy.oj.dao.discussion.CommentEntityService;
import web.suzy.oj.dao.discussion.DiscussionEntityService;
import web.suzy.oj.dao.discussion.ReplyEntityService;
import web.suzy.oj.dao.msg.MsgRemindEntityService;
import web.suzy.oj.dao.msg.UserSysNoticeEntityService;
import web.suzy.oj.pojo.entity.discussion.Comment;
import web.suzy.oj.pojo.entity.discussion.Discussion;
import web.suzy.oj.pojo.entity.discussion.Reply;
import web.suzy.oj.pojo.entity.msg.MsgRemind;
import web.suzy.oj.pojo.entity.msg.UserSysNotice;
import web.suzy.oj.pojo.vo.UserMsgVO;
import web.suzy.oj.pojo.vo.UserUnreadMsgCountVO;
import web.suzy.oj.shiro.AccountProfile;

import javax.annotation.Resource;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * YangSuzy 软件工作室
 * 类名: UserMessageManager
 * 描述: ---- 待定 -----
 * 功能: ---- 待定 -----
 *
 * @author YangSuzy
 * Date: 2022/11/18 18:02
 */
@Component
public class UserMessageManager {
    @Resource
    private MsgRemindEntityService msgRemindEntityService;

    @Resource
    private UserSysNoticeEntityService userSysNoticeEntityService;

    @Resource
    private DiscussionEntityService discussionEntityService;

    @Resource
    private CommentEntityService commentEntityService;

    @Resource
    private ReplyEntityService replyEntityService;

    @Resource
    private ApplicationContext applicationContext;

    /**
     * 方法名: getUnreadMsgCount
     * 描述: 获取用户未读消息
     *
     * @return web.suzy.oj.pojo.vo.UserUnreadMsgCountVO
     * @date 2022/11/18 18:02
     * @auther YangSuzy
     **/
    public UserUnreadMsgCountVO getUnreadMsgCount() {
        //获取当前登录的用户
        AccountProfile userRolesVo = (AccountProfile) SecurityUtils.getSubject().getPrincipal();
        UserUnreadMsgCountVO userUnreadMsgCount = msgRemindEntityService.getUserUnreadMsgCount(userRolesVo.getUid());
        //查询为空值手动设置未读消息为0
        if (userUnreadMsgCount == null) {
            userUnreadMsgCount = new UserUnreadMsgCountVO(0, 0, 0, 0, 0);
        }
        return userUnreadMsgCount;
    }

    /**
     * 方法名: cleanMsg
     * 描述: 根据消息类型清空一类消息，或根据消息ID清空一条消息
     *
     * @param type 消息类型
     * @param id   消息ID
     * @return void
     * @date 2022/11/18 22:44
     * @auther YangSuzy
     **/
    public void cleanMsg(String type, Long id) throws StatusFailException {
        // 获取当前登录的用户
        AccountProfile userRolesVo = (AccountProfile) SecurityUtils.getSubject().getPrincipal();
        //根据传入类型清空消息
        boolean isOk = cleanMsgByType(type, id, userRolesVo.getUid());
        if (!isOk) {
            throw new StatusFailException("清空失败");
        }
    }

    /**
     * 方法名: cleanMsgByType
     * 描述: 根据传入类型清空消息
     *
     * @param type 消息类型
     * @param id   消息ID
     * @param uid  用户ID
     * @return boolean
     * @date 2022/11/27 22:44
     * @auther YangSuzy
     **/
    private boolean cleanMsgByType(String type, Long id, String uid) {
        switch (type) {
            case "Like":
            case "Discuss":
            case "Reply":
                UpdateWrapper<MsgRemind> updateWrapper1 = new UpdateWrapper<>();
                updateWrapper1.eq(id != null, "id", id).eq("recipient_id", uid);
                //移除点赞、讨论、评论消息
                return msgRemindEntityService.remove(updateWrapper1);
            case "Sys":
            case "Mine":
                UpdateWrapper<UserSysNotice> updateWrapper2 = new UpdateWrapper<>();
                updateWrapper2.eq(id != null, "id", id).eq("recipient_id", uid);
                //移除系统、我的消息
                return userSysNoticeEntityService.remove(updateWrapper2);
            default:
                return false;
        }
    }

    /**
     * 方法名: getCommentMsg
     * 描述: 获取用户接收的评论消息提示
     *
     * @param limit       每页显示数目
     * @param currentPage 当前页
     * @return com.baomidou.mybatisplus.core.metadata.IPage<web.suzy.oj.pojo.vo.UserMsgVO>
     * @date 2022/11/27 22:38
     * @auther YangSuzy
     **/
    public IPage<UserMsgVO> getCommentMsg(Integer limit, Integer currentPage) {
        //设置默认当前页和每页默认显示数目
        if (currentPage == null || currentPage < 1) {
            currentPage = 1;
        }
        if (limit == null || limit < 1) {
            limit = 5;
        }
        // 获取当前登录的用户
        AccountProfile userRolesVo = (AccountProfile) SecurityUtils.getSubject().getPrincipal();

        return getUserMsgList(userRolesVo.getUid(), "Discuss", limit, currentPage);
    }

    /**
     * 方法名: getReplyMsg
     * 描述: 获取用户接收的回复消息提示
     *
     * @param limit       每页显示数目
     * @param currentPage 当前页
     * @return com.baomidou.mybatisplus.core.metadata.IPage<web.suzy.oj.pojo.vo.UserMsgVO>
     * @date 2022/11/27 23:01
     * @auther YangSuzy
     **/
    public IPage<UserMsgVO> getReplyMsg(Integer limit, Integer currentPage) {
        //设置默认当前页和每页默认显示数目
        if (currentPage == null || currentPage < 1) {
            currentPage = 1;
        }
        if (limit == null || limit < 1) {
            limit = 5;
        }
        // 获取当前登录的用户
        AccountProfile userRolesVo = (AccountProfile) SecurityUtils.getSubject().getPrincipal();

        return getUserMsgList(userRolesVo.getUid(), "Reply", limit, currentPage);
    }

    /**
     * 方法名: getLikeMsg
     * 描述: 获取用户接收的点赞消息提示
     *
     * @param limit       每页显示数目
     * @param currentPage 当前页
     * @return com.baomidou.mybatisplus.core.metadata.IPage<web.suzy.oj.pojo.vo.UserMsgVO>
     * @date 2022/11/27 23:17
     * @auther YangSuzy
     **/
    public IPage<UserMsgVO> getLikeMsg(Integer limit, Integer currentPage) {
        //设置默认当前页和每页默认显示数目
        if (currentPage == null || currentPage < 1) {
            currentPage = 1;
        }
        if (limit == null || limit < 1) {
            limit = 5;
        }

        // 获取当前登录的用户
        AccountProfile userRolesVo = (AccountProfile) SecurityUtils.getSubject().getPrincipal();

        return getUserMsgList(userRolesVo.getUid(), "Like", limit, currentPage);
    }

    /**
     * 方法名: getUserMsgList
     * 描述: 根据消息类型获取用户消息提示列表
     *
     * @param uid         用户ID
     * @param action      消息类型：评论、回复、点赞
     * @param limit       每页显示数目
     * @param currentPage 当前页
     * @return com.baomidou.mybatisplus.core.metadata.IPage<web.suzy.oj.pojo.vo.UserMsgVO>
     * @date 2022/11/27 22:40
     * @auther YangSuzy
     **/
    private IPage<UserMsgVO> getUserMsgList(String uid, String action, int limit, int currentPage) {
        Page<UserMsgVO> page = new Page<>(currentPage, limit);
        //根据消息类型获取用户提示消息列表
        IPage<UserMsgVO> userMsgList = msgRemindEntityService.getUserMsg(page, uid, action);
        if (userMsgList.getTotal() > 0) {
            switch (action) {
                //评论我的
                case "Discuss":
                    return getUserDiscussMsgList(userMsgList);
                //回复我的
                case "Reply":
                    return getUserReplyMsgList(userMsgList);
                //点赞我的
                case "Like":
                    return getUserLikeMsgList(userMsgList);
                default:
                    throw new RuntimeException("invalid action:" + action);
            }
        } else {
            return userMsgList;
        }
    }

    /**
     * 方法名: getUserDiscussMsgList
     * 描述: 获取用户的讨论消息提示列表
     *
     * @param userMsgList 用户消息列表
     * @return com.baomidou.mybatisplus.core.metadata.IPage<web.suzy.oj.pojo.vo.UserMsgVO>
     * @date 2022/11/27 22:42
     * @auther YangSuzy
     **/
    private IPage<UserMsgVO> getUserDiscussMsgList(IPage<UserMsgVO> userMsgList) {
        //根据用户消息提示列表获取讨论ID列表
        List<Integer> discussionIds = userMsgList.getRecords()
                .stream()
                .map(UserMsgVO::getSourceId)
                .collect(Collectors.toList());
        //根据讨论ID获取讨论实体对象集
        Collection<Discussion> discussions = discussionEntityService.listByIds(discussionIds);
        for (Discussion discussion : discussions) {
            for (UserMsgVO userMsgVo : userMsgList.getRecords()) {
                if (Objects.equals(discussion.getId(), userMsgVo.getSourceId())) {
                    //设置讨论标题为用户消息提示中的标题
                    userMsgVo.setSourceTitle(discussion.getTitle());
                    break;
                }
            }
        }
        //通过spring上下文对象获取本类的更新用户已读消息提示方法
        applicationContext.getBean(UserMessageManager.class).updateUserMsgRead(userMsgList);
        return userMsgList;
    }

    /**
     * 方法名: getUserReplyMsgList
     * 描述: 获取用户的回复消息提示列表
     *
     * @param userMsgList 用户消息列表
     * @return com.baomidou.mybatisplus.core.metadata.IPage<web.suzy.oj.pojo.vo.UserMsgVO>
     * @date 2022/11/27 23:03
     * @auther YangSuzy
     **/
    private IPage<UserMsgVO> getUserReplyMsgList(IPage<UserMsgVO> userMsgList) {

        for (UserMsgVO userMsgVo : userMsgList.getRecords()) {
            if ("Discussion".equals(userMsgVo.getSourceType())) {
                //根据事件源ID获取引用的讨论
                Discussion discussion = discussionEntityService.getById(userMsgVo.getSourceId());
                if (discussion != null) {
                    //设置讨论标题为用户消息提示中事件源的标题
                    userMsgVo.setSourceTitle(discussion.getTitle());
                } else {
                    userMsgVo.setSourceTitle("原讨论帖已被删除!【The original discussion post has been deleted!】");
                }
            }

            if ("Comment".equals(userMsgVo.getQuoteType())) {
                //根据引用ID获取评论
                Comment comment = commentEntityService.getById(userMsgVo.getQuoteId());
                if (comment != null) {
                    String content;
                    if (comment.getContent().length() < 100) {
                        content = comment.getFromName() + " : "
                                + comment.getContent();
                    } else {
                        //评论内容超出100个字符时将超出部分换成省略号
                        content = comment.getFromName() + " : "
                                + comment.getContent().substring(0, 100) + "...";
                    }
                    //设置消息提示的引用内容
                    userMsgVo.setQuoteContent(content);
                } else {
                    userMsgVo.setQuoteContent("您的原评论信息已被删除！【Your original comments have been deleted!】");
                }
            } else if ("Reply".equals(userMsgVo.getQuoteType())) {
                //根据引用ID获取回复
                Reply reply = replyEntityService.getById(userMsgVo.getQuoteId());
                if (reply != null) {
                    String content;
                    if (reply.getContent().length() < 100) {
                        content = reply.getFromName() + " : @" + reply.getToName() + "："
                                + reply.getContent();
                    } else {
                        //回复内容超出100个字符时将超出部分换成省略号
                        content = reply.getFromName() + " : @" + reply.getToName() + "："
                                + reply.getContent().substring(0, 100) + "...";
                    }
                    //设置消息提示的引用内容
                    userMsgVo.setQuoteContent(content);
                } else {
                    userMsgVo.setQuoteContent("您的原回复信息已被删除！【Your original reply has been deleted!】");
                }
            }
        }
        //通过spring上下文对象获取本类的更新用户已读消息提示方法
        applicationContext.getBean(UserMessageManager.class).updateUserMsgRead(userMsgList);
        return userMsgList;
    }

    /**
     * 方法名: getUserLikeMsgList
     * 描述: 获取用户的回复消息提示列表
     *
     * @param userMsgList 用户消息列表
     * @return com.baomidou.mybatisplus.core.metadata.IPage<web.suzy.oj.pojo.vo.UserMsgVO>
     * @date 2022/11/27 23:18
     * @auther YangSuzy
     **/
    private IPage<UserMsgVO> getUserLikeMsgList(IPage<UserMsgVO> userMsgList) {
        for (UserMsgVO userMsgVo : userMsgList.getRecords()) {
            if ("Discussion".equals(userMsgVo.getSourceType())) {
                //根据事件源ID获取引用的讨论
                Discussion discussion = discussionEntityService.getById(userMsgVo.getSourceId());
                if (discussion != null) {
                    //设置讨论标题为用户消息提示中事件源的标题
                    userMsgVo.setSourceTitle(discussion.getTitle());
                } else {
                    userMsgVo.setSourceTitle("原讨论帖已被删除!【The original discussion post has been deleted!】");
                }
            }
        }
        //通过spring上下文对象获取本类的更新用户已读消息提示方法
        applicationContext.getBean(UserMessageManager.class).updateUserMsgRead(userMsgList);
        return userMsgList;
    }

    /**
     * 方法名: updateUserMsgRead
     * 描述: 异步方法 - 更新用户已读消息提示
     *
     * @param userMsgList 用户消息提示列表
     * @return void
     * @date 2022/11/27 22:54
     * @auther YangSuzy
     **/
    @Async
    public void updateUserMsgRead(IPage<UserMsgVO> userMsgList) {
        //根据用户消息提示列表获取ID
        List<Long> idList = userMsgList.getRecords().stream()
                .filter(userMsgVo -> !userMsgVo.getState())
                .map(UserMsgVO::getId)
                .collect(Collectors.toList());
        if (idList.size() == 0) {
            return;
        }
        //将用户消息提示更新为已读
        UpdateWrapper<MsgRemind> updateWrapper = new UpdateWrapper<>();
        updateWrapper.in("id", idList)
                .set("state", true);
        msgRemindEntityService.update(null, updateWrapper);
    }
}
